package com.megvii.koala.tv.presenter;

import android.os.Handler;
import android.os.Looper;

import com.android.volley.VolleyError;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.megvii.corelib.filechooser.FileChooseEvent;
import com.megvii.corelib.filechooser.FileChooserActivity;
import com.megvii.corelib.filechooser.FileChooserLayoutParam;
import com.megvii.corelib.net.Callback;
import com.megvii.corelib.util.AlertDialogUtil;
import com.megvii.corelib.util.AppUtil;
import com.megvii.corelib.util.StorageUtil;
import com.megvii.koala.base.KoalaPresenter;
import com.megvii.koala.constance.ErrorCode;
import com.megvii.koala.guard.Box;
import com.megvii.koala.tv.R;
import com.megvii.koala.tv.data.ServerManager;
import com.megvii.koala.tv.data.SurveillanceCameraManager;
import com.megvii.koala.tv.data.TVBoxManager;
import com.megvii.koala.tv.data.TVGlobalData;
import com.megvii.koala.tv.event.ChooseThemeEvent;
import com.megvii.koala.tv.event.ClickMenuRefreshEvent;
import com.megvii.koala.tv.event.ClickMenuRegisterEvent;
import com.megvii.koala.tv.event.MenuFocusEvent;
import com.megvii.koala.tv.event.ScreenConfigCompleteEvent;
import com.megvii.koala.tv.fragment.WebFragment;
import com.megvii.koala.tv.net.TVNetAPI;
import com.megvii.koala.tv.net.tv.SetDeviceInfoResponse;
import com.megvii.koala.tv.video.VideoManager;
import com.megvii.koala.tv.video.VideoManagerEx;
import com.megvii.koala.tv.video.VideoManagerInterface;
import com.megvii.koala.tv.video.VideoManagerListener;
import com.megvii.koala.tv.web.KoalaTvUrls;
import com.megvii.koala.tv.web.KoalaTvWebView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by linyue on 16/1/24.
 */
public class WebPresenter extends KoalaPresenter<WebFragment>
        implements KoalaTvWebView.KoalaTvWebViewListener, TVBoxManager.TVBoxManagerListener, ServerManager.ServerManagerListener, VideoManagerListener, BDLocationListener {
    private Handler handler = new Handler(Looper.getMainLooper());

    private ServerManager serverManager;

    private TVBoxManager boxManager;

    private SurveillanceCameraManager cameraManager;


    private VideoManagerInterface videoManagerLocal;

    private VideoManagerInterface videoManagerNet;

    private boolean menuFocusingOnRegister = false;

    private float leftForLocalVideo;

    private float topForLocalVideo;

    private float widthForLocalVideo;

    private float heightForLocalVideo;

    private boolean localVideoMode = true;

    private boolean needRefreshBox = false;

    private boolean needCallBackPlay = false;

    private RefreshThread refreshThread;

    private LocationClient locationClient;

    private BDLocation location;

    @Override
    protected void onCreated() {
        super.onCreated();
        serverManager = TVGlobalData.instance().serverManager;
        serverManager.setListener(this);
        boxManager = TVGlobalData.instance().boxManager;
        boxManager.registerListener(this);
        cameraManager = TVGlobalData.instance().cameraManager;
        videoManagerLocal = new VideoManagerEx();
        videoManagerLocal
                .init(viewHolder.getActivity().getWindow(), viewHolder.getVideoSurfaceLocal());
        videoManagerLocal.setListener(this);

        videoManagerNet = new VideoManager();
        videoManagerNet.init(viewHolder.getActivity().getWindow(), viewHolder.getVideoSurfaceNet());
        videoManagerNet.setListener(this);

        viewHolder.setWebViewListener(this);
        refreshThread = new RefreshThread();
        refreshThread.start();
        //
        initLocation();
        refreshWeb();
    }

    @Override
    protected void onStart() {
        super.onStart();
        getVideoManager().restartPlay();
    }

    @Override
    protected void onDestory() {
        super.onDestory();
        refreshThread.interrupt();
        viewHolder.setWebViewListener(null);
        videoManagerLocal.release();
        videoManagerNet.release();
        boxManager.unregisterListener(this);
        serverManager.setListener(null);
        releaseLocation();
    }

    public void refreshWeb() {
        String boxToken = boxManager.getSelectedToken();
        String boxAddress = boxManager.getSelectedAddress();
        if (boxToken != null && boxAddress != null &&
                cameraManager.isPersistented()) {
            viewHolder.showVideo(false);
            viewHolder.loadWeb(serverManager.getAddress() + KoalaTvUrls.SCREEN);
            locationClient.start();
        }
    }

    public void refreshBox() {
        if (needRefreshBox) {
            String boxToken = boxManager.getSelectedToken();
            String boxAddress = boxManager.getSelectedAddress();
            if (boxToken != null && boxAddress != null &&
                    cameraManager.isPersistented()) {
                String deviceToken = AppUtil.getDeviceUUID(viewHolder.getActivity());
                viewHolder.showVideo(false);
                viewHolder.getWebAPI().KCDiscovery(boxToken, boxAddress, deviceToken);
            }
        }
        needRefreshBox = false;
    }

    public boolean isLocalVideoMode() {
        return localVideoMode;
    }

    private VideoManagerInterface getVideoManager() {
        return localVideoMode ? videoManagerLocal : videoManagerNet;
    }

    @Override
    public void onPageStartLoading(String url) {

    }

    @Override
    public void onPageFinished(String url) {
        refreshBox();
    }

    //web callback start
    @Override
    public void onPageError(int errorCode, String description, String failingUrl) {

    }

    @Override
    public void onProgressChanged(int newProgress) {

    }

    @Override
    public void onPlayVideo(String src, final float left, final float top, final float width,
                            final float height) {
        getVideoManager().stop();
        localVideoMode = false;
        playVideo(src, left, top, width, height);
    }

    @Override
    public void onPlayLocalVideo(float left, float top, float width, float height) {
        getVideoManager().stop();
        localVideoMode = true;
        leftForLocalVideo = left;
        topForLocalVideo = top;
        widthForLocalVideo = width;
        heightForLocalVideo = height;
        //判断是否选择了本地文件
        if (TVGlobalData.instance().fileManager.has_local_file()) {
            //开始播放
            viewHolder.showNotChooseFileLayout(false);
            playVideo(TVGlobalData.instance().fileManager.getLocal_theme_path(), leftForLocalVideo, topForLocalVideo, widthForLocalVideo,
                    heightForLocalVideo);
        } else {
            needCallBackPlay = true;
            //将没有视频的文字显示
            viewHolder.showNotChooseFileLayout(true);
//            showFileChooser();
        }
    }

    private void playVideo(String src, float left, float top, float width, float height) {
        viewHolder.showSurfaceView(localVideoMode);
        if (menuFocusingOnRegister) {
            //焦点在一键注册上，就只把位置存下来
            viewHolder.resizeVideoContainer(left, top, width, height, true, false);
        } else {
            viewHolder.resizeVideoContainer(left, top, width, height, true, true);
        }
        if (src != null && !src.isEmpty()) {
            viewHolder.showVideo(true);
            getVideoManager().play(src);
        } else {
            viewHolder.showVideo(false);
            getVideoManager().clearSrc();
        }
    }

    private void showFileChooser() {
        List<String> postfixed = new ArrayList<>();
        postfixed.add(".avi");
        postfixed.add(".mp4");
        postfixed.add(".3gp");
        postfixed.add(".mov");
        String[] rootArray = StorageUtil.getStorageList();
        List<String> roots = new ArrayList<>();
        if (rootArray != null) {
            for (String root : rootArray) {
                roots.add(root);
            }
        }
        FileChooserLayoutParam param = new FileChooserLayoutParam(R.layout.tv_filechooser_layout,
                R.layout.box_item, R.id.box_item_text, roots, postfixed);
        for (int i = 0; i < 3; i++) {
            viewHolder.startActivity(FileChooserActivity.class, param);
        }
    }

    @Override
    public void onOpenDoor() {

    }
    //web callback end

    //event bus start

    /**
     * 菜单点击手动刷新
     *
     * @param event
     */
    public void onEvent(ClickMenuRefreshEvent event) {
        needRefreshBox = true;
        refreshWeb();
        //在这里需要重新刷新视频流
        getVideoManager().restartPlay();
    }

    /**
     * 菜单点击一键注册
     *
     * @param event
     */
    public void onEvent(ClickMenuRegisterEvent event) {
        viewHolder.getWebAPI().KCUpload();
    }

    /**
     * 选择主题
     *
     * @param event
     */
    public void onEvent(ChooseThemeEvent event) {
        viewHolder.getWebAPI().KCTheme(event.theme);
    }

    /**
     * 焦点是否在菜单的“一键注册”上
     *
     * @param event
     */
    public void onEvent(MenuFocusEvent event) {
        menuFocusingOnRegister = event.focusedOnRegister;
        if (event.focusedOnRegister) {
            viewHolder.resizeVideoContainer(0, 0, 1, 1, false, true);
            viewHolder.showWebView(false);
        } else {
            viewHolder.recoverVideoContainerSize();
            viewHolder.showWebView(true);
        }
    }

    /**
     * 选择播放本地文件结束
     *
     * @param event
     */
    public void onEvent(FileChooseEvent event) {
        //在这里保存文件信息
        TVGlobalData.instance().fileManager.setLocal_theme_path(event.fileAbsolutePath);
        if (needCallBackPlay) {
            needCallBackPlay = false;
            playVideo(TVGlobalData.instance().fileManager.getLocal_theme_path(), leftForLocalVideo, topForLocalVideo, widthForLocalVideo,
                    heightForLocalVideo);
        }
        //刷新界面
        refreshWeb();
    }

    /**
     * 屏幕设置（包括用于识别的视频流、屏幕显示的视频流）
     *
     * @param event
     */
    public void onEvent(ScreenConfigCompleteEvent event) {
        needRefreshBox = true;
        refreshWeb();
    }

    //event bus end

    //box callback start
    @Override
    public void onNewBoxSearched(Box box) {

    }

    @Override
    public void onSelectionChanged(Box box) {

    }

    @Override
    public void onClearSelection() {
        //TODO do something to clear display
    }
    //box callback end

    //server callback start
    @Override
    public void onAddressChanged(String address) {

    }

    @Override
    public void onVideoError(int errorCode) {
        AlertDialogUtil
                .showMessage(viewHolder.getActivity(), ErrorCode.getDescription(errorCode), null);
    }

    //baidu lbs location start
    @Override
    public void onReceiveLocation(BDLocation bdLocation) {
        locationClient.stop();
        this.location = bdLocation;
        requestSetDeviceInfo();
        //        showToast(bdLocation.getCity() + "   " + bdLocation.getCityCode());
    }

    private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(
                LocationClientOption.LocationMode.Hight_Accuracy);//可选，默认高精度，设置定位模式，高精度，低功耗，仅设备
        option.setCoorType("bd09ll");//可选，默认gcj02，设置返回的定位结果坐标系
        int span = 1000;
        option.setScanSpan(span);//可选，默认0，即仅定位一次，设置发起定位请求的间隔需要大于等于1000ms才是有效的
        option.setIsNeedAddress(true);//可选，设置是否需要地址信息，默认不需要
        option.setOpenGps(true);//可选，默认false,设置是否使用gps
        option.setLocationNotify(true);//可选，默认false，设置是否当gps有效时按照1S1次频率输出GPS结果
        option.setIsNeedLocationDescribe(
                true);//可选，默认false，设置是否需要位置语义化结果，可以在BDLocation.getLocationDescribe里得到，结果类似于“在北京天安门附近”
        option.setIsNeedLocationPoiList(true);//可选，默认false，设置是否需要POI结果，可以在BDLocation.getPoiList里得到
        option.setIgnoreKillProcess(
                false);//可选，默认true，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认不杀死
        option.SetIgnoreCacheException(false);//可选，默认false，设置是否收集CRASH信息，默认收集
        option.setEnableSimulateGps(false);//可选，默认false，设置是否需要过滤gps仿真结果，默认需要
        locationClient = new LocationClient(viewHolder.getActivity());
        locationClient.registerLocationListener(this);
        locationClient.setLocOption(option);
    }

    private void releaseLocation() {
        locationClient.unRegisterLocationListener(this);
        locationClient.stop();
    }

    private void requestSetDeviceInfo() {
        String cityName = location.getCity(); //TODO 获取不到城市的情况需要处理
        if (cityName != null && !cityName.equals("")) {
            int len = cityName.length();
            String lastChar = cityName.substring(len - 1, len);
            //TODO 嘻嘻，可不是我要这么做的哦~~~以后server找用经纬度的天气接口 或 我直接传天气。。。
            if (lastChar.equals("市")) {
                cityName = cityName.substring(0, len - 1);
            }
            TVNetAPI.requestSetDeviceInfo(AppUtil.getDeviceUUID(viewHolder.getActivity()), cityName,
                    this, this);
        }
    }

    @Callback(clazz = SetDeviceInfoResponse.class)
    public void onSetDeviceInfoResponse(SetDeviceInfoResponse response) {
        if (response.code != ErrorCode.NO_ERROR) {
            showToast(ErrorCode.getDescription(response.code));
        }
    }

    @Override
    public void onErrorResponse(VolleyError error) {
        super.onErrorResponse(error);
        //TODO 以后如果这个类要加其他的网络消息处理，那么这里就要做判断是不是要重发set device info请求了
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                requestSetDeviceInfo();
            }
        }, 6000);
    }
    //baidu lbs location end

    public class RefreshThread extends Thread {
        private volatile boolean terminated = false;

        @Override
        public void run() {
            while (!terminated) {
                try {
                    sleep(1000);
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (localVideoMode) {
                                int currentTime = videoManagerLocal.getVideoCurrentTime();
                                int durationTime = videoManagerLocal.getVideoDuration();
                                if (currentTime >= 0 && durationTime >= 0) {
                                    viewHolder.setSeekBarVisible(true);
                                    viewHolder.setVideoCurrentTime(currentTime);
                                    viewHolder.setVideoDurationTime(durationTime);
                                } else {
                                    viewHolder.setSeekBarVisible(false);
                                }
                            }
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void interrupt() {
            terminated = true;
            super.interrupt();
        }
    }
}
